﻿extern alias ClusterAgg;
using System;
using System.Collections.Generic;
using System.Security.Permissions;
using Microsoft.Win32;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Threading;
using System.IO;
using ClusterAgg.ClusterAggregation.ClusterAggregators;
using ClusterAgg.ClusterAggregation.Clusterers;
using ClusterAgg.ClusterAggregation.DataSets;
using ClusterAgg.ClusterAggregation.Datum;


namespace WindowsFormsApplication1
{

    public partial class CMainGUI : Form
    {
        private bool usePAM;
        private bool useKMeans;
        private bool useMCLA;
        private bool useCSPA;
        private bool useCASLA;
        private double VYSmoothNum;
        private bool m_IsAborting;
        private List<CResultGUI> m_guis;
        private List<BackgroundWorker> m_workers;        
        private AutoResetEvent m_resetEvent;
        private ClusterAgg.ClusterAggregation.Datum.AData[] m_dataArr;
        private DateTime m_startTime;
        private Guid m_CASLA_currentguid;
        private Guid m_CSPA_currentguid;
        private Guid m_MCLA_currentguid;
        //private List<threadFunctionDelegate> m_tfd;
        private List<IAsyncResult> m_asyngResult;
        private Form m_paramsArray;
        private List<double> m_smoothingList;
        public string m_historyPath = "history.txt";
        public static CPartition m_partition;
        public static CPartition m_CSPA_partition;
        public static CPartition m_MCLA_partition;
        public static CPartition m_CASLA_partition;
        BackgroundWorker CASLAWorker;
        BackgroundWorker MCLAWorker;
        BackgroundWorker CSPAWorker;
        BackgroundWorker partitionWorker;
        public string m_filePath = "";
        public string m_currentSelectedCellPath;
        public string m_chosenAlgorithm = "";
        public int m_clusteringSize = 0;
        private ClusterAgg.ClusterAggregation.Datum.ISimilarity m_distFunc;
        private ClusterAgg.ClusterAggregation.DataSets.CPartition[] m_parpartitionArray;
        private object m_lock = new object();

        public CMainGUI()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            readHistory();            
            ClusterNumber.SelectedIndex = 1;
            m_guis = new List<CResultGUI>();
            m_resetEvent = new AutoResetEvent(false);
            //m_tfd = new List<threadFunctionDelegate>();
            m_asyngResult = new List<IAsyncResult>();
            m_workers = new List<BackgroundWorker>();            
            useCASLA = CASLACheckBox.Checked;
            useCSPA = CSPACheckBox.Checked;
            useKMeans = kMeansCheckBox.Checked;
            useMCLA = MCLACheckBox.Checked;
            usePAM = PamCheckBox.Checked;
            double smoo;
            if (double.TryParse(VYSmooth.Text, out smoo))
                VYSmoothNum = smoo;
            else
                VYSmoothNum = 0.0;
            m_IsAborting = false;
        }

        private void readHistory()
        {
            if (System.IO.File.Exists(m_historyPath))
            {
                TextReader tr = new StreamReader(m_historyPath);
                while (tr.Peek() >= 0)
                {
                    string[] strs = tr.ReadLine().Split('#');
                    string[] row = new string[] { strs[0], strs[1], strs[2], strs[3], strs[4] };
                    dataGridView1.Rows.Add(row);
                }
                tr.Close();
                dataGridView1.Refresh();
            }
        }

        private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
        {

        }

        private void folderBrowserDialog1_HelpRequest(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            DialogResult result = openFileDialog1.ShowDialog();
            if (result == DialogResult.OK) // Test result.
            {                
                string file = openFileDialog1.FileName;
                richTextBox1.Text = file;
                m_filePath = file;          
            }  
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void statusStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private void toolStripStatusLabel1_Click(object sender, EventArgs e)
        {

        }

        private void openFileDialog1_FileOk_1(object sender, CancelEventArgs e)
        {

        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void button2_Click(object sender, EventArgs e)
        {
            m_startTime = DateTime.Now;
            m_IsAborting = false;
            if (this.Controls.Find("button5", true).Length > 0)
                this.Controls.Find("button5", true)[0].Enabled = true;

            if (m_filePath != "")
            {
                CFileHandler handler = new CFileHandler();
                this.toolStripStatusLabel1.Text = "Started";                
                if (m_filePath.EndsWith("txt"))
                {
                    m_dataArr = handler.ReadFile(m_filePath);
                    m_distFunc = new ClusterAgg.ClusterAggregation.Datum.CEuclideanDistanceSimilarityFunction();
                }
                else if (m_filePath.EndsWith("dts"))
                {
                    m_dataArr = ClusterAgg.ClusterAggregation.GeneralTools.CDatasetReader.readDataArray(m_filePath);
                    m_distFunc = new ClusterAgg.ClusterAggregation.Datum.CEuclideanDistanceSimilarityFunction();
                }
                else if (m_filePath.ToLower().EndsWith("ico") || m_filePath.ToLower().EndsWith("jpg") || m_filePath.ToLower().EndsWith("bmp") || m_filePath.ToLower().EndsWith("jpeg") || m_filePath.ToLower().EndsWith("png"))
                {
                    m_dataArr = handler.ReadImage(m_filePath);
                    m_distFunc = new ClusterAgg.ClusterAggregation.Datum.CGreyscaledPixelDistanceFunction();
                }
                else
                {
                    m_dataArr = null;
                }
                if (m_dataArr != null && m_dataArr.Length > 0)
                {                    
                    toolStripProgressBar1.Step = 2;
                    foreach (Control control in this.Controls)
                    {
                        if (!control.Name.Equals("button5"))
                            control.Enabled = false;
                    }
                    //empty last run m_guis
                    m_guis.RemoveRange(0, m_guis.Count);
                    
                    m_parpartitionArray = null;                    
                    //generate partitions
                    
                    BackgroundWorker worker0 = new BackgroundWorker();
                    m_workers.Add(worker0);
                    worker0.WorkerSupportsCancellation = true;
                    worker0.WorkerReportsProgress = true;
                    worker0.DoWork += new DoWorkEventHandler(worker_DoWork);
                    worker0.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                    worker0.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
                    worker0.RunWorkerAsync();
                    //threadFunctionDelegate t0 = new threadFunctionDelegate(partitionGeneratingFunction);
                    //m_tfd.Add(t0);
                    //m_asyngResult.Add(t0.BeginInvoke(m_dataArr, clb, t0.Method.ToString()));                                        

                    partitionWorker = new BackgroundWorker();                 
                    partitionWorker.WorkerSupportsCancellation = true;
                    partitionWorker.WorkerReportsProgress = false;
                    partitionWorker.DoWork += new DoWorkEventHandler(partition_worker_DoWork);
                    partitionWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(partitionWorker_RunWorkerCompleted);
                    partitionWorker.RunWorkerAsync(m_dataArr);

                    if (CSPACheckBox.Checked)
                    {
                        BackgroundWorker worker1 = new BackgroundWorker();
                        m_workers.Add(worker1);
                        worker1.WorkerSupportsCancellation = true;
                        worker1.WorkerReportsProgress = true;
                        worker1.DoWork += new DoWorkEventHandler(worker_DoWork);
                        worker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                        worker1.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
                        worker1.RunWorkerAsync();
                        //threadFunctionDelegate t1 = new threadFunctionDelegate(CSPAFunction);
                        //m_tfd.Add(t1);
                        //m_asyngResult.Add(t1.BeginInvoke(m_dataArr, clb, t1.Method.ToString()));    

                        CSPAWorker = new BackgroundWorker();
                        CSPAWorker.WorkerSupportsCancellation = true;
                        CSPAWorker.WorkerReportsProgress = false;
                        CSPAWorker.DoWork += new DoWorkEventHandler(CSPAWorker_DoWork);
                        CSPAWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CSPAWorker_RunWorkerCompleted);
                        CSPAWorker.RunWorkerAsync(m_dataArr);
                    }
                    if(MCLACheckBox.Checked)
                    {
                        BackgroundWorker worker2 = new BackgroundWorker();
                        m_workers.Add(worker2);
                        worker2.WorkerSupportsCancellation = true;
                        worker2.WorkerReportsProgress = true;
                        worker2.DoWork += new DoWorkEventHandler(worker_DoWork);
                        worker2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                        worker2.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
                        worker2.RunWorkerAsync();
                        //threadFunctionDelegate t2 = new threadFunctionDelegate(MCLAFunction);
                        //m_tfd.Add(t2);
                        //m_asyngResult.Add(t2.BeginInvoke(m_dataArr, clb, t2.Method.ToString()));

                        MCLAWorker = new BackgroundWorker();
                        MCLAWorker.WorkerSupportsCancellation = true;
                        MCLAWorker.WorkerReportsProgress = false;
                        MCLAWorker.DoWork += new DoWorkEventHandler(MCLAWorker_DoWork);
                        MCLAWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(MCLAWorker_RunWorkerCompleted);
                        MCLAWorker.RunWorkerAsync(m_dataArr);
                    }
                    if(CASLACheckBox.Checked)
                    {
                        BackgroundWorker worker3 = new BackgroundWorker();
                        m_workers.Add(worker3);
                        worker3.WorkerSupportsCancellation = true;
                        worker3.WorkerReportsProgress = true;
                        worker3.DoWork += new DoWorkEventHandler(worker_DoWork);
                        worker3.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                        worker3.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
                        worker3.RunWorkerAsync();
                        //threadFunctionDelegate t3 = new threadFunctionDelegate(CASLAFunction);
                        //m_tfd.Add(t3);
                        //m_asyngResult.Add(t3.BeginInvoke(m_dataArr, clb, t3.Method.ToString()));

                        CASLAWorker = new BackgroundWorker();                                               
                        CASLAWorker.WorkerSupportsCancellation = true;
                        CASLAWorker.WorkerReportsProgress = false;
                        CASLAWorker.DoWork += new DoWorkEventHandler(CASLAWorker_DoWork);
                        CASLAWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CASLAWorker_RunWorkerCompleted);
                        CASLAWorker.RunWorkerAsync(m_dataArr);
                    }                                        
                }
            }
        }

        void CASLAWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            ClusterAgg.ClusterAggregation.Datum.AData[] arr = (ClusterAgg.ClusterAggregation.Datum.AData[])e.Argument;

            while (m_parpartitionArray == null) System.Threading.Thread.Sleep(10);
            lock (m_lock) { }

            ClusterAgg.ClusterAggregation.ClusterAggregators.CVolkovichYahalom caslaAgg = new ClusterAgg.ClusterAggregation.ClusterAggregators.CVolkovichYahalom();
            m_CASLA_partition = caslaAgg.ensemble(m_parpartitionArray, arr, m_clusteringSize);
        }

        void CASLAWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!m_IsAborting)
            {
                if (m_CASLA_partition == null)
                {
                    m_workers[0].CancelAsync();
                    m_resetEvent.WaitOne();
                    m_workers.RemoveAt(0);
                    return;
                }
                m_CASLA_currentguid = Guid.NewGuid();
                CResultGUI g = null;

                if (m_filePath.EndsWith("txt"))
                {
                    double maxw = 0, maxh = 0, minw = 0, minh = 0;
                    for (int i = 0; i < m_dataArr.Length; i++)
                    {
                        if (m_dataArr[i].coordinates[0] > maxw)
                            maxw = m_dataArr[i].coordinates[0];
                        if (m_dataArr[i].coordinates[0] < minw)
                            minw = m_dataArr[i].coordinates[0];

                        if (m_dataArr[i].coordinates[1] > maxh)
                            maxh = m_dataArr[i].coordinates[1];
                        if (m_dataArr[i].coordinates[1] < minh)
                            minh = m_dataArr[i].coordinates[1];
                    }
                    CResultData data = new CResultData();
                    data.algorithm = "CASLA";
                    string anmi = String.Format("{0:0.00}", m_CASLA_partition.compareTo(m_parpartitionArray));
                    double anmid;
                    if (double.TryParse(anmi.Substring(0, 4), out anmid))
                        data.ANMI = anmid;
                    else
                        data.ANMI = 0.0;
                    data.arr = m_dataArr;
                    data.gid = m_CASLA_currentguid;
                    data.partition = m_CASLA_partition;
                    data.path = m_filePath;
                    data.w = (int)(1 + maxw - minw);
                    data.h = (int)(1 + maxh - minh);
                    data.NumberOfClusters = m_clusteringSize;
                    data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
                    g = new CResultGUI(data);
                    m_guis.Add(g);
                    //guis.Add(new ResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, (int)(1 + maxw - minw), (int)(1 + maxh - minh), filePath, currentguid));
                }
                if (m_filePath.ToLower().EndsWith("ico") || m_filePath.ToLower().EndsWith("jpg") || m_filePath.ToLower().EndsWith("bmp") || m_filePath.ToLower().EndsWith("jpeg") || m_filePath.ToLower().EndsWith("png"))
                {
                    Bitmap b = new Bitmap(m_filePath);
                    CResultData data = new CResultData();
                    data.algorithm = "CASLA";
                    string anmi = String.Format("{0:0.00}", m_CASLA_partition.compareTo(m_parpartitionArray));
                    double anmid;
                    if (double.TryParse(anmi.Substring(0, 4), out anmid))
                        data.ANMI = anmid;
                    else
                        data.ANMI = 0.0;
                    data.arr = m_dataArr;
                    data.gid = m_CASLA_currentguid;
                    data.partition = m_CASLA_partition;
                    data.path = m_filePath;
                    data.w = b.Width;
                    data.h = b.Height;
                    data.NumberOfClusters = m_clusteringSize;
                    data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
                    g = new CResultGUI(data);
                    m_guis.Add(g);
                    //guis.Add(new ResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, b.Width, b.Height, filePath, currentguid));

                }
                else
                { // default for txt or dts
                    double maxw = 0, maxh = 0, minw = 0, minh = 0;
                    for (int i = 0; i < m_dataArr.Length; i++)
                    {
                        if (m_dataArr[i].coordinates[0] > maxw)
                            maxw = m_dataArr[i].coordinates[0];
                        if (m_dataArr[i].coordinates[0] < minw)
                            minw = m_dataArr[i].coordinates[0];

                        if (m_dataArr[i].coordinates[1] > maxh)
                            maxh = m_dataArr[i].coordinates[1];
                        if (m_dataArr[i].coordinates[1] < minh)
                            minh = m_dataArr[i].coordinates[1];
                    }
                    CResultData data = new CResultData();
                    data.algorithm = "CASLA";
                    string anmi = String.Format("{0:0.00}", m_CASLA_partition.compareTo(m_parpartitionArray));
                    double anmid;
                    if (double.TryParse(anmi.Substring(0, 4), out anmid))
                        data.ANMI = anmid;
                    else
                        data.ANMI = 0.0;
                    data.arr = m_dataArr;
                    data.gid = m_CASLA_currentguid;
                    data.partition = m_CASLA_partition;
                    data.path = m_filePath;
                    data.w = (int)(1 + maxw - minw);
                    data.h = (int)(1 + maxh - minh);
                    data.NumberOfClusters = m_clusteringSize;
                    data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
                    g = new CResultGUI(data);
                    m_guis.Add(g);
                    //guis.Add(new ResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, (int)(1 + maxw - minw), (int)(1 + maxh - minh), filePath, currentguid));
                }

                //save partition and display new resultgui form
                if (g != null)
                {
                    string algo = "";
                    g.Show();
                    if (g.Controls.Find("textbox1", true).Length > 0)
                        algo = g.Controls.Find("textbox1", true)[0].Text;
                    string[] row = new string[] { DateTime.Now.ToString(), m_filePath, algo, m_clusteringSize.ToString(), DateTime.Now.Subtract(m_startTime).ToString() };
                    dataGridView1.Rows.Add(row);
                    dataGridView1.Refresh();

                    TextWriter tr = null;
                    try
                    {
                        tr = System.IO.File.AppendText(m_historyPath);
                        tr.WriteLine(row[0] + '#' + row[1] + '#' + row[2] + '#' + row[3] + '#' + row[4]);
                    }
                    catch (Exception)
                    {
                        // do nothing
                    }
                    finally
                    {
                        if(null != tr)
                            tr.Close();
                    }

                    //save partition to a file...
                    if (m_CASLA_partition != null)
                        ClusterAgg.ClusterAggregation.GeneralTools.CDatasetWriter.writeParition(row[1] + row[0].Replace('/', '_').Replace(':', '_') + ".prt", m_CASLA_partition);

                    g.FormClosing += new FormClosingEventHandler(g_FormClosing);
                }
            }
            if (m_workers.Count > 0)
            {
                m_workers[0].CancelAsync();
                m_resetEvent.WaitOne();
                m_workers.RemoveAt(0);
            }
        }

        void MCLAWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            ClusterAgg.ClusterAggregation.Datum.AData[] arr = (ClusterAgg.ClusterAggregation.Datum.AData[])e.Argument;

            while (m_parpartitionArray == null) System.Threading.Thread.Sleep(10);
            lock (m_lock) { }

            ClusterAgg.ClusterAggregation.ClusterAggregators.CMCLA mclaAgg = new ClusterAgg.ClusterAggregation.ClusterAggregators.CMCLA();
            m_MCLA_partition = mclaAgg.ensemble(m_parpartitionArray, arr, m_clusteringSize);
        }

        void MCLAWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!m_IsAborting)
            {
                if (m_MCLA_partition == null)
                {
                    m_workers[0].CancelAsync();
                    m_resetEvent.WaitOne();
                    m_workers.RemoveAt(0);
                    return;
                }
                m_MCLA_currentguid = Guid.NewGuid();
                CResultGUI g = null;

                if (m_filePath.EndsWith("txt"))
                {
                    double maxw = 0, maxh = 0, minw = 0, minh = 0;
                    for (int i = 0; i < m_dataArr.Length; i++)
                    {
                        if (m_dataArr[i].coordinates[0] > maxw)
                            maxw = m_dataArr[i].coordinates[0];
                        if (m_dataArr[i].coordinates[0] < minw)
                            minw = m_dataArr[i].coordinates[0];

                        if (m_dataArr[i].coordinates[1] > maxh)
                            maxh = m_dataArr[i].coordinates[1];
                        if (m_dataArr[i].coordinates[1] < minh)
                            minh = m_dataArr[i].coordinates[1];
                    }
                    CResultData data = new CResultData();
                    data.algorithm = "MCLA";
                    string anmi = String.Format("{0:0.00}", m_MCLA_partition.compareTo(m_parpartitionArray));
                    double anmid;
                    if (double.TryParse(anmi.Substring(0, 4), out anmid))
                        data.ANMI = anmid;
                    else
                        data.ANMI = 0.0;
                    data.arr = m_dataArr;
                    data.gid = m_MCLA_currentguid;
                    data.partition = m_MCLA_partition;
                    data.path = m_filePath;
                    data.w = (int)(1 + maxw - minw);
                    data.h = (int)(1 + maxh - minh);
                    data.NumberOfClusters = m_clusteringSize;
                    data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
                    g = new CResultGUI(data);
                    m_guis.Add(g);
                    //guis.Add(new ResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, (int)(1 + maxw - minw), (int)(1 + maxh - minh), filePath, currentguid));
                }
                if (m_filePath.ToLower().EndsWith("ico") || m_filePath.ToLower().EndsWith("jpg") || m_filePath.ToLower().EndsWith("bmp") || m_filePath.ToLower().EndsWith("jpeg") || m_filePath.ToLower().EndsWith("png"))
                {
                    Bitmap b = new Bitmap(m_filePath);
                    CResultData data = new CResultData();
                    data.algorithm = "MCLA";
                    string anmi = String.Format("{0:0.00}", m_MCLA_partition.compareTo(m_parpartitionArray));
                    double anmid;
                    if (double.TryParse(anmi.Substring(0, 4), out anmid))
                        data.ANMI = anmid;
                    else
                        data.ANMI = 0.0;
                    data.arr = m_dataArr;
                    data.gid = m_MCLA_currentguid;
                    data.partition = m_MCLA_partition;
                    data.path = m_filePath;
                    data.w = b.Width;
                    data.h = b.Height;
                    data.NumberOfClusters = m_clusteringSize;
                    data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
                    g = new CResultGUI(data);
                    m_guis.Add(g);
                    //guis.Add(new ResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, b.Width, b.Height, filePath, currentguid));

                }
                else
                { // default for txt or dts
                    double maxw = 0, maxh = 0, minw = 0, minh = 0;
                    for (int i = 0; i < m_dataArr.Length; i++)
                    {
                        if (m_dataArr[i].coordinates[0] > maxw)
                            maxw = m_dataArr[i].coordinates[0];
                        if (m_dataArr[i].coordinates[0] < minw)
                            minw = m_dataArr[i].coordinates[0];

                        if (m_dataArr[i].coordinates[1] > maxh)
                            maxh = m_dataArr[i].coordinates[1];
                        if (m_dataArr[i].coordinates[1] < minh)
                            minh = m_dataArr[i].coordinates[1];
                    }
                    CResultData data = new CResultData();
                    data.algorithm = "MCLA";
                    string anmi = String.Format("{0:0.00}", m_MCLA_partition.compareTo(m_parpartitionArray));
                    double anmid;
                    if (double.TryParse(anmi.Substring(0, 4), out anmid))
                        data.ANMI = anmid;
                    else
                        data.ANMI = 0.0;
                    data.arr = m_dataArr;
                    data.gid = m_MCLA_currentguid;
                    data.partition = m_MCLA_partition;
                    data.path = m_filePath;
                    data.w = (int)(1 + maxw - minw);
                    data.h = (int)(1 + maxh - minh);
                    data.NumberOfClusters = m_clusteringSize;
                    data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
                    g = new CResultGUI(data);
                    m_guis.Add(g);
                    //guis.Add(new ResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, (int)(1 + maxw - minw), (int)(1 + maxh - minh), filePath, currentguid));
                }

                //save partition and display new resultgui form
                if (g != null)
                {
                    string algo = "";
                    g.Show();
                    if (g.Controls.Find("textbox1", true).Length > 0)
                        algo = g.Controls.Find("textbox1", true)[0].Text;
                    string[] row = new string[] { DateTime.Now.ToString(), m_filePath, algo, m_clusteringSize.ToString(), DateTime.Now.Subtract(m_startTime).ToString() };
                    dataGridView1.Rows.Add(row);
                    dataGridView1.Refresh();
                    
                    TextWriter tr = null;
                    try
                    {
                        tr = System.IO.File.AppendText(m_historyPath);
                        tr.WriteLine(row[0] + '#' + row[1] + '#' + row[2] + '#' + row[3] + '#' + row[4]);
                    }
                    catch (Exception)
                    {
                        // do nothing
                    }
                    finally
                    {
                        if (null != tr)
                            tr.Close();
                    }

                   
                    //save partition to a file...
                    if (m_MCLA_partition != null)
                        ClusterAgg.ClusterAggregation.GeneralTools.CDatasetWriter.writeParition(row[1] + row[0].Replace('/', '_').Replace(':', '_') + ".prt", m_MCLA_partition);

                    g.FormClosing += new FormClosingEventHandler(g_FormClosing);
                }
            }
            if (m_workers.Count > 0)
            {
                m_workers[0].CancelAsync();
                m_resetEvent.WaitOne();
                m_workers.RemoveAt(0);
            }
        }

        void CSPAWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            ClusterAgg.ClusterAggregation.Datum.AData[] arr = (ClusterAgg.ClusterAggregation.Datum.AData[])e.Argument;

            while (m_parpartitionArray == null) System.Threading.Thread.Sleep(10);
            lock (m_lock) { }

            ClusterAgg.ClusterAggregation.ClusterAggregators.CCSPA cspaAgg = new ClusterAgg.ClusterAggregation.ClusterAggregators.CCSPA();
            m_CSPA_partition = cspaAgg.ensemble(m_parpartitionArray, arr, m_clusteringSize);            
        }

        void CSPAWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!m_IsAborting)
            {
                if (m_CSPA_partition == null)
                {
                    m_workers[0].CancelAsync();
                    m_resetEvent.WaitOne();
                    m_workers.RemoveAt(0);
                    return;
                }
                m_CSPA_currentguid = Guid.NewGuid();
                CResultGUI g = null;

                if (m_filePath.EndsWith("txt"))
                {
                    double maxw = 0, maxh = 0, minw = 0, minh = 0;
                    for (int i = 0; i < m_dataArr.Length; i++)
                    {
                        if (m_dataArr[i].coordinates[0] > maxw)
                            maxw = m_dataArr[i].coordinates[0];
                        if (m_dataArr[i].coordinates[0] < minw)
                            minw = m_dataArr[i].coordinates[0];

                        if (m_dataArr[i].coordinates[1] > maxh)
                            maxh = m_dataArr[i].coordinates[1];
                        if (m_dataArr[i].coordinates[1] < minh)
                            minh = m_dataArr[i].coordinates[1];
                    }
                    CResultData data = new CResultData();
                    data.algorithm = "CSPA";
                    string anmi = String.Format("{0:0.00}", m_CSPA_partition.compareTo(m_parpartitionArray));
                    double anmid;
                    if (double.TryParse(anmi.Substring(0, 4), out anmid))
                        data.ANMI = anmid;
                    else
                        data.ANMI = 0.0;
                    data.arr = m_dataArr;
                    data.gid = m_CSPA_currentguid;
                    data.partition = m_CSPA_partition;
                    data.path = m_filePath;
                    data.w = (int)(1 + maxw - minw);
                    data.h = (int)(1 + maxh - minh);
                    data.NumberOfClusters = m_clusteringSize;
                    data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
                    g = new CResultGUI(data);
                    m_guis.Add(g);
                    //guis.Add(new ResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, (int)(1 + maxw - minw), (int)(1 + maxh - minh), filePath, currentguid));
                }
                if (m_filePath.ToLower().EndsWith("ico") || m_filePath.ToLower().EndsWith("jpg") || m_filePath.ToLower().EndsWith("bmp") || m_filePath.ToLower().EndsWith("jpeg") || m_filePath.ToLower().EndsWith("png"))
                {
                    Bitmap b = new Bitmap(m_filePath);
                    CResultData data = new CResultData();
                    data.algorithm = "CSPA";
                    string anmi = String.Format("{0:0.00}", m_CSPA_partition.compareTo(m_parpartitionArray));
                    double anmid;
                    if (double.TryParse(anmi.Substring(0, 4), out anmid))
                        data.ANMI = anmid;
                    else
                        data.ANMI = 0.0;
                    data.arr = m_dataArr;
                    data.gid = m_CSPA_currentguid;
                    data.partition = m_CSPA_partition;
                    data.path = m_filePath;
                    data.w = b.Width;
                    data.h = b.Height;
                    data.NumberOfClusters = m_clusteringSize;
                    data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
                    g = new CResultGUI(data);
                    m_guis.Add(g);
                    //guis.Add(new ResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, b.Width, b.Height, filePath, currentguid));

                }
                else
                { // default for txt or dts
                    double maxw = 0, maxh = 0, minw = 0, minh = 0;
                    for (int i = 0; i < m_dataArr.Length; i++)
                    {
                        if (m_dataArr[i].coordinates[0] > maxw)
                            maxw = m_dataArr[i].coordinates[0];
                        if (m_dataArr[i].coordinates[0] < minw)
                            minw = m_dataArr[i].coordinates[0];

                        if (m_dataArr[i].coordinates[1] > maxh)
                            maxh = m_dataArr[i].coordinates[1];
                        if (m_dataArr[i].coordinates[1] < minh)
                            minh = m_dataArr[i].coordinates[1];
                    }
                    CResultData data = new CResultData();
                    data.algorithm = "CSPA";
                    string anmi = String.Format("{0:0.00}", m_CSPA_partition.compareTo(m_parpartitionArray));
                    double anmid;
                    if (double.TryParse(anmi.Substring(0, 4), out anmid))
                        data.ANMI = anmid;
                    else
                        data.ANMI = 0.0;
                    data.arr = m_dataArr;
                    data.gid = m_CSPA_currentguid;
                    data.partition = m_CSPA_partition;
                    data.path = m_filePath;
                    data.w = (int)(1 + maxw - minw);
                    data.h = (int)(1 + maxh - minh);
                    data.NumberOfClusters = m_clusteringSize;
                    data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
                    g = new CResultGUI(data);
                    m_guis.Add(g);
                    //guis.Add(new ResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, (int)(1 + maxw - minw), (int)(1 + maxh - minh), filePath, currentguid));
                }
                
                //save partition and display new resultgui form
                if (g != null)
                {
                    string algo = "";
                    g.Show();
                    if (g.Controls.Find("textbox1", true).Length > 0)
                        algo = g.Controls.Find("textbox1", true)[0].Text;
                    string[] row = new string[] { DateTime.Now.ToString(), m_filePath, algo, m_clusteringSize.ToString(), DateTime.Now.Subtract(m_startTime).ToString() };
                    dataGridView1.Rows.Add(row);
                    dataGridView1.Refresh();
                    
                   
                    TextWriter tr = null;
                    try
                    {
                        tr = System.IO.File.AppendText(m_historyPath);
                        tr.WriteLine(row[0] + '#' + row[1] + '#' + row[2] + '#' + row[3] + '#' + row[4]);
                    }
                    catch (Exception)
                    {
                        // do nothing
                    }
                    finally
                    {
                        if (null != tr)
                            tr.Close();
                    }

                   
                    //save partition to a file...
                    if (m_CSPA_partition != null)
                        ClusterAgg.ClusterAggregation.GeneralTools.CDatasetWriter.writeParition(row[1] + row[0].Replace('/', '_').Replace(':', '_') + ".prt", m_CSPA_partition);

                    g.FormClosing += new FormClosingEventHandler(g_FormClosing);
                }
            }
            if (m_workers.Count > 0)
            {
                m_workers[0].CancelAsync();
                m_resetEvent.WaitOne();
                m_workers.RemoveAt(0);
            }
        }

        private void partition_worker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            ClusterAgg.ClusterAggregation.Datum.AData[] arr = (ClusterAgg.ClusterAggregation.Datum.AData[])e.Argument;
            lock (m_lock)
            {
                string[] tmp = this.SpectralSmoothingArray.Text.Split(' ');
                LinkedList<double> prmList = new LinkedList<double>();

                foreach (var item in tmp)
                {
                    if (null != item && item != "")
                    {
                        try
                        {
                            double arg = double.Parse(item);
                            prmList.AddLast(arg);
                        }
                        finally
                        { }
                    }
                }

                CPartitionGenerator gen = new CPartitionGenerator(m_distFunc);
                m_parpartitionArray = gen.generatePartitions(arr, m_distFunc, m_clusteringSize, this.kMeansCheckBox.Checked, this.PamCheckBox.Checked, prmList.ToArray());

            }            
        }

        void partitionWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            m_workers[0].CancelAsync();
            m_resetEvent.WaitOne();
            m_workers.RemoveAt(0);
        }

        private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            int p = 0;
            while (!worker.CancellationPending)
            {
                p++;
                worker.ReportProgress(p);
                if (p == 99)
                    p = 0;
                System.Threading.Thread.Sleep(200);
            }
            m_resetEvent.Set();
        }

        private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (m_workers.Count == 0)
            {
                toolStripProgressBar1.Value = 0;
                foreach (Control control in this.Controls)
                {
                    if (control.Name.Equals("button5"))
                        control.Enabled = false;
                    else
                        control.Enabled = true;
                }
                this.toolStripStatusLabel1.Text = "Finished";
            }            

            //foreach (CResultGUI g in m_guis)
            //{
            //    if (g.id.Equals(m_currentguid))
            //    {
            //        string algo = "";
            //        g.Show();
            //        if(g.Controls.Find("textbox1", true).Length > 0)
            //             algo = g.Controls.Find("textbox1", true)[0].Text;
            //        string[] row = new string[] { DateTime.Now.ToString(), m_filePath, algo, m_clusteringSize.ToString(), DateTime.Now.Subtract(m_startTime).ToString() };
            //        dataGridView1.Rows.Add(row);
            //        dataGridView1.Refresh();
            //        TextWriter tr = System.IO.File.AppendText(m_historyPath);
            //        tr.WriteLine(row[0] + '#' + row[1] + '#' + row[2] + '#' + row[3] + '#' + row[4]);
            //        tr.Close();
            //        //save partition to a file...
            //        if (m_partition != null)
            //            ClusterAgg.ClusterAggregation.GeneralTools.CDatasetWriter.writeParition(row[1] + row[0].Replace('/', '_').Replace(':', '_') + ".prt", m_partition);
            //    }
            //    g.FormClosing += new FormClosingEventHandler(g_FormClosing);
            //}                        
        }

        private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (toolStripProgressBar1 != null && toolStripProgressBar1.ProgressBar != null)
            {
                if (toolStripProgressBar1.Value == toolStripProgressBar1.Maximum)
                    toolStripProgressBar1.Value = 0;
                toolStripProgressBar1.PerformStep();
            }
        }

        void g_FormClosing(object sender, FormClosingEventArgs e)
        {            
            foreach (CResultGUI g in m_guis)
            {
                if (g.id.Equals(((CResultGUI)sender).id))
                {
                    m_guis.Remove(g);
                    return;
                }
            }
        }        

        //private void clb(IAsyncResult iar)
        //{
        //    System.Runtime.Remoting.Messaging.AsyncResult results = (System.Runtime.Remoting.Messaging.AsyncResult)iar;
        //    m_partition = ((threadFunctionDelegate)results.AsyncDelegate).EndInvoke(iar);
        //    if (m_partition == null)
        //    {
        //        m_workers[0].CancelAsync();
        //        m_resetEvent.WaitOne();
        //        m_workers.RemoveAt(0);
        //        return;
        //    }
        //    m_currentguid = Guid.NewGuid();
            
        //    if (m_filePath.EndsWith("txt"))
        //    {
        //        double maxw = 0, maxh = 0, minw = 0, minh = 0;
        //        for (int i = 0; i < m_dataArr.Length; i++)
        //        {
        //            if (m_dataArr[i].coordinates[0] > maxw)
        //                maxw = m_dataArr[i].coordinates[0];
        //            if (m_dataArr[i].coordinates[0] < minw)
        //                minw = m_dataArr[i].coordinates[0];

        //            if (m_dataArr[i].coordinates[1] > maxh)
        //                maxh = m_dataArr[i].coordinates[1];
        //            if (m_dataArr[i].coordinates[1] < minh)
        //                minh = m_dataArr[i].coordinates[1];
        //        }
        //        CResultData data = new CResultData();
        //        if(((string)iar.AsyncState).Contains("MCLA"))
        //            data.algorithm = "MCLA";
        //        else if(((string)iar.AsyncState).Contains("CSPA"))
        //            data.algorithm = "CSPA";
        //        else if (((string)iar.AsyncState).Contains("CASLA"))
        //            data.algorithm = "CASLA";
        //        string anmi = String.Format("{0:0.00}", m_partition.compareTo(m_parpartitionArray));
        //        double anmid;
        //        if (double.TryParse(anmi.Substring(0, 4), out anmid))
        //            data.ANMI = anmid;
        //        else
        //            data.ANMI = 0.0;
        //        data.arr = m_dataArr;
        //        data.gid = m_currentguid;
        //        data.partition = m_partition;
        //        data.path = m_filePath;
        //        data.w = (int)(1 + maxw - minw);
        //        data.h = (int)(1 + maxh - minh);
        //        data.NumberOfClusters = m_clusteringSize;
        //        data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
        //        m_guis.Add(new CResultGUI(data));
        //        //guis.Add(new ResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, (int)(1 + maxw - minw), (int)(1 + maxh - minh), filePath, currentguid));
        //    }
        //    if (m_filePath.ToLower().EndsWith("ico") || m_filePath.ToLower().EndsWith("jpg") || m_filePath.ToLower().EndsWith("bmp") || m_filePath.ToLower().EndsWith("jpeg") || m_filePath.ToLower().EndsWith("png"))
        //    {
        //        Bitmap b = new Bitmap(m_filePath);
        //        CResultData data = new CResultData();
        //        if (((string)iar.AsyncState).Contains("MCLA"))
        //            data.algorithm = "MCLA";
        //        else if (((string)iar.AsyncState).Contains("CSPA"))
        //            data.algorithm = "CSPA";
        //        else if (((string)iar.AsyncState).Contains("CASLA"))
        //            data.algorithm = "CASLA";
        //        string anmi = String.Format("{0:0.00}", m_partition.compareTo(m_parpartitionArray));
        //        double anmid;
        //        if (double.TryParse(anmi.Substring(0, 4), out anmid))
        //            data.ANMI = anmid;
        //        else
        //            data.ANMI = 0.0;
        //        data.arr = m_dataArr;
        //        data.gid = m_currentguid;
        //        data.partition = m_partition;
        //        data.path = m_filePath;
        //        data.w = b.Width;
        //        data.h = b.Height;
        //        data.NumberOfClusters = m_clusteringSize;
        //        data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
        //        m_guis.Add(new CResultGUI(data));
        //        //guis.Add(new ResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, b.Width, b.Height, filePath, currentguid));

        //    }
        //    else
        //    { // default for txt or dts
        //        double maxw = 0, maxh = 0, minw = 0, minh = 0;
        //        for (int i = 0; i < m_dataArr.Length; i++)
        //        {
        //            if (m_dataArr[i].coordinates[0] > maxw)
        //                maxw = m_dataArr[i].coordinates[0];
        //            if (m_dataArr[i].coordinates[0] < minw)
        //                minw = m_dataArr[i].coordinates[0];

        //            if (m_dataArr[i].coordinates[1] > maxh)
        //                maxh = m_dataArr[i].coordinates[1];
        //            if (m_dataArr[i].coordinates[1] < minh)
        //                minh = m_dataArr[i].coordinates[1];
        //        }                
        //        CResultData data = new CResultData();
        //        if (((string)iar.AsyncState).Contains("MCLA"))
        //            data.algorithm = "MCLA";
        //        else if (((string)iar.AsyncState).Contains("CSPA"))
        //            data.algorithm = "CSPA";
        //        else if (((string)iar.AsyncState).Contains("CASLA"))
        //            data.algorithm = "CASLA";
        //        string anmi = String.Format("{0:0.00}", m_partition.compareTo(m_parpartitionArray));
        //        double anmid;
        //        if (double.TryParse(anmi.Substring(0, 4), out anmid))
        //            data.ANMI = anmid;
        //        else
        //            data.ANMI = 0.0;
        //        data.arr = m_dataArr;
        //        data.gid = m_currentguid;
        //        data.partition = m_partition;
        //        data.path = m_filePath;
        //        data.w = (int)(1 + maxw - minw);
        //        data.h = (int)(1 + maxh - minh);
        //        data.NumberOfClusters = m_clusteringSize;
        //        data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
        //        m_guis.Add(new CResultGUI(data));
        //        //guis.Add(new ResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, (int)(1 + maxw - minw), (int)(1 + maxh - minh), filePath, currentguid));
        //    }
        //    m_workers[0].CancelAsync();
        //    m_resetEvent.WaitOne();
        //    m_workers.RemoveAt(0);    
        //}

        //private delegate ClusterAgg.ClusterAggregation.DataSets.CPartition threadFunctionDelegate(ClusterAgg::ClusterAggregation.Datum.AData[] arr);

        //private ClusterAgg.ClusterAggregation.DataSets.CPartition MCLAFunction(ClusterAgg::ClusterAggregation.Datum.AData[] arr)
        //{
        //    //System.Threading.Thread.wait
        //    while (m_parpartitionArray == null) System.Threading.Thread.Sleep(10);
        //    lock (m_lock) { }

        //    ClusterAgg.ClusterAggregation.ClusterAggregators.CMCLA mclaAgg = new ClusterAgg.ClusterAggregation.ClusterAggregators.CMCLA();
        //    m_partition = mclaAgg.ensemble(m_parpartitionArray, arr, m_clusteringSize);

        //    return m_partition;
        //}
        
        //private ClusterAgg.ClusterAggregation.DataSets.CPartition partitionGeneratingFunction(ClusterAgg::ClusterAggregation.Datum.AData[] arr)
        //{
        //    lock (m_lock)
        //    {
        //        string[] tmp = this.SpectralSmoothingArray.Text.Split(' ');
        //        LinkedList<double> prmList = new LinkedList<double>();

        //        foreach (var item in tmp)
        //        {
        //            if (null != item && item != "")
        //            {
        //                try
        //                {
        //                    double arg = double.Parse(item);
        //                    prmList.AddLast(arg);
        //                }
        //                finally
        //                { }
        //            }                    
        //        }

        //        CPartitionGenerator gen = new CPartitionGenerator(m_distFunc);
        //        m_parpartitionArray = gen.generatePartitions(arr, m_distFunc, m_clusteringSize, this.kMeansCheckBox.Checked, this.PamCheckBox.Checked, prmList.ToArray());
             
        //    }
        //    return null;
        //}

        //private ClusterAgg.ClusterAggregation.DataSets.CPartition CSPAFunction(ClusterAgg::ClusterAggregation.Datum.AData[] arr)
        //{
        //    while (m_parpartitionArray == null) System.Threading.Thread.Sleep(10);
        //    lock (m_lock) { }

        //    ClusterAgg.ClusterAggregation.ClusterAggregators.CCSPA cspaAgg = new ClusterAgg.ClusterAggregation.ClusterAggregators.CCSPA();
        //    m_partition = cspaAgg.ensemble(m_parpartitionArray, arr, m_clusteringSize);

        //    return m_partition;
        //}

        //private ClusterAgg.ClusterAggregation.DataSets.CPartition CASLAFunction(ClusterAgg::ClusterAggregation.Datum.AData[] arr)
        //{
        //    while (m_parpartitionArray == null) System.Threading.Thread.Sleep(10);
        //    lock (m_lock) { }

        //    ClusterAgg.ClusterAggregation.ClusterAggregators.CVolkovichYahalom caslaAgg = new ClusterAgg.ClusterAggregation.ClusterAggregators.CVolkovichYahalom();
        //    m_partition = caslaAgg.ensemble(m_parpartitionArray, arr, m_clusteringSize);

        //    return m_partition;
        //}

        //private ClusterAgg.ClusterAggregation.DataSets.CPartition kMeansFunction(ClusterAgg::ClusterAggregation.Datum.AData[] arr)
        //{
        //    IClusterer clusterer = new ClusterAgg.ClusterAggregation.Clusterers.CKMeansImpl();
        //    ISimilarity distFunc = new ClusterAgg.ClusterAggregation.Datum.CGreyscaledPixelDistanceFunction();
        //    CPartition partition = clusterer.cluster(arr, distFunc, m_clusteringSize);
        //    return partition;
        //}

        //private ClusterAgg.ClusterAggregation.DataSets.CPartition spectralFunction(ClusterAgg::ClusterAggregation.Datum.AData[] arr)
        //{
        //    IClusterer clusterer = new ClusterAgg.ClusterAggregation.Clusterers.CSpectralClusterer();
        //    ISimilarity distFunc = new ClusterAgg.ClusterAggregation.Datum.CGreyscaledPixelDistanceFunction();
        //    CPartition partition = clusterer.cluster(arr, distFunc, m_clusteringSize);
        //    return partition;
        //}

        //private ClusterAgg.ClusterAggregation.DataSets.CPartition pamFunction(ClusterAgg::ClusterAggregation.Datum.AData[] arr)
        //{
        //    IClusterer clusterer = new ClusterAgg.ClusterAggregation.Clusterers.CPamImpl();
        //    ISimilarity distFunc = new ClusterAgg.ClusterAggregation.Datum.CGreyscaledPixelDistanceFunction();
        //    CPartition partition = clusterer.cluster(arr, distFunc, m_clusteringSize);
        //    return partition;
        //}  

        private void toolStripProgressBar1_Click(object sender, EventArgs e)
        {

        }

        private void MainGUI_FormClosing(Object sender, FormClosingEventArgs e)
        {
            if (m_workers.Count != 0)
            {
                foreach (BackgroundWorker w in m_workers)
                {
                    w.CancelAsync();
                }                
            }
            Application.Exit();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            TextWriter tr = null;
            try
            {
                FileInfo info = new FileInfo(m_historyPath);
                tr = new StreamWriter(info.Open(FileMode.Truncate));
                tr.Close();
                dataGridView1.Rows.Clear();
            }
            catch (Exception)
            {
                // do nothing
            }
            finally
            {
                if (null != tr)
                    tr.Close();
            }
        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            m_currentSelectedCellPath = dataGridView1[1, e.RowIndex].Value.ToString();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (System.IO.File.Exists(m_currentSelectedCellPath))
            {
                richTextBox1.Text = m_currentSelectedCellPath;
                m_filePath = m_currentSelectedCellPath;
            }
        }        

        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            int size;
            if(int.TryParse((((ComboBox)sender).SelectedItem).ToString(), out size))
                m_clusteringSize = size;
            if (m_clusteringSize <= 0)
                m_clusteringSize = 2;
        }

        private void dataGridView1_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
        {           
            string partitionPath = dataGridView1[1, ((DataGridView)sender).CurrentCellAddress.Y].Value.ToString() + dataGridView1[0, ((DataGridView)sender).CurrentCellAddress.Y].Value.ToString().Replace('/', '_').Replace(':', '_') + ".prt";
            string dataPath = dataGridView1[1, ((DataGridView)sender).CurrentCellAddress.Y].Value.ToString();
            if (System.IO.File.Exists(dataPath) && System.IO.File.Exists(partitionPath))
            {
                ClusterAgg.ClusterAggregation.Datum.AData[] arr = ClusterAgg.ClusterAggregation.GeneralTools.CDatasetReader.readDataArray(dataPath);
                ClusterAgg.ClusterAggregation.DataSets.CPartition partition = ClusterAgg.ClusterAggregation.GeneralTools.CDatasetReader.readParition(partitionPath);
                double maxw = 0, maxh = 0, minw = 0, minh = 0;
                for (int i = 0; i < arr.Length; i++)
                {
                    if (arr[i].coordinates[0] > maxw)
                        maxw = arr[i].coordinates[0];
                    if (arr[i].coordinates[0] < minw)
                        minw = arr[i].coordinates[0];

                    if (arr[i].coordinates[1] > maxh)
                        maxh = arr[i].coordinates[1];
                    if (arr[i].coordinates[1] < minh)
                        minh = arr[i].coordinates[1];
                }
                Guid gid = Guid.NewGuid();
                string algorithm = dataGridView1[2, ((DataGridView)sender).CurrentCellAddress.Y].Value.ToString();                
                CResultData data = new CResultData();
                data.algorithm = algorithm;
                if (m_parpartitionArray != null)
                {
                    string anmi = String.Format("{0:0.00}", partition.compareTo(m_parpartitionArray));
                    double anmid;
                    if (double.TryParse(anmi.Substring(0, 4), out anmid))
                        data.ANMI = anmid;
                    else
                        data.ANMI = 0.0;
                }
                else
                    data.ANMI = 0.0;
                data.arr = arr;
                data.gid = gid;
                data.partition = partition;
                data.path = dataPath;
                data.w = (int)(1 + maxw - minw);
                data.h = (int)(1 + maxh - minh);
                data.NumberOfClusters = m_clusteringSize;
                if (m_parpartitionArray != null)
                    data.NumberOfPartitions = m_parpartitionArray.ToList<ClusterAgg.ClusterAggregation.DataSets.CPartition>().Count;
                else
                    data.NumberOfPartitions = 0;
                CResultGUI gui = new CResultGUI(data);
                
                //CResultGUI gui = new CResultGUI(arr, (ClusterAgg.ClusterAggregation.DataSets.CPartition)partition, (int)(1 + maxw - minw), (int)(1 + maxh - minh), dataPath, gid);
                gui.Show();
            }
        }

        private void importToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
          
            DialogResult result = openFileDialog2.ShowDialog();
            if (result == DialogResult.OK) // Test result.
            {
                string file = openFileDialog2.FileName;
                LinkedList<ClusterAgg.ClusterAggregation.Datum.AData> datalist = new LinkedList<ClusterAgg.ClusterAggregation.Datum.AData>();
                double maxh = 0, minh = 5000, maxw = 0, minw = 5000;
               
                // get all data
                ClusterAgg.ClusterAggregation.DataSets.CPartition prtsn =
                    ClusterAgg.ClusterAggregation.GeneralTools.CDatasetReader.readParition(file);

                foreach (var cls in prtsn.clusters)
                {
                    foreach (var datums in cls.data)
                    {
                        datalist.AddFirst(datums);
                        if (datums.coordinates[0] > maxw)
                            maxw = datums.coordinates[0];
                        if (datums.coordinates[0] < minw)
                            minw = datums.coordinates[0];

                        if (datums.coordinates[1] > maxh)
                            maxh = datums.coordinates[1];
                        if (datums.coordinates[1] < minh)
                            minh = datums.coordinates[1];
                    }
                }
                Guid gid = Guid.NewGuid();
                Form resGUI = new CResultGUI(datalist.ToArray(), prtsn, (int)(2 + maxw), (int)(2 + maxh), file, gid);
                resGUI.Show();
            }  
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void helpToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                string path = Path.Combine(Environment.CurrentDirectory, @"..\html\index.html");
                openWithDefault(path);
            }
            catch (Exception ) { }
       
        }

        private void viewSourceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string path = "http://code.google.com/p/braude-cluster-project";
            openWithDefault(path);
        }

        private void aboutUsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form abt = new About();
            abt.Show();
        }

        private void openFileDialog2_FileOk(object sender, CancelEventArgs e)
        {

        } 
        private void openWithDefault(string name)
        {
            System.Diagnostics.Process myProcess = new System.Diagnostics.Process();

            try
            {
                // true is the default, but it is important not to set it to false
                myProcess.StartInfo.UseShellExecute = true;
                myProcess.StartInfo.FileName = name;
                myProcess.Start();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        private void label6_Click(object sender, EventArgs e)
        {

        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void textBox1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            m_smoothingList = new List<double>();
            if (m_paramsArray == null)
            {
                m_paramsArray = new ParamsArray(out m_smoothingList);
                m_paramsArray.ShowDialog();
            }
            else
            {
                m_paramsArray.Close();
                m_paramsArray = new ParamsArray(out m_smoothingList);
                m_paramsArray.ShowDialog();
            }
            string smooth = "";
            foreach (double doub in m_smoothingList)
            {
                smooth += ' '+doub.ToString();
            }
            SpectralSmoothingArray.Text = smooth;
        }

        private void textBox1_TextChanged_1(object sender, EventArgs e)
        {

        }

        private void checkBox3_Click(object sender, EventArgs e)
        {
            if (this.VYSmooth.Enabled)
                this.VYSmooth.Enabled = false;
            else
                this.VYSmooth.Enabled = true;
        }

        private void VYSmooth_Leave(object sender, EventArgs e)
        {
            double x = 1;
            Double.TryParse(VYSmooth.Text, out x);
            if (x == 0)
                VYSmooth.Text = "1";
        }

        private void comboBox2_Leave(object sender, EventArgs e)
        {
            int size;
            int.TryParse(ClusterNumber.Text, out size);
            m_clusteringSize = size;
            if (m_clusteringSize <= 0)
            {
                m_clusteringSize = 2;
                ClusterNumber.Text = "2";
            }
        }
        
        private void PamCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            usePAM = ((CheckBox)sender).Checked;
        }

        private void kMeansCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            useKMeans = ((CheckBox)sender).Checked;
        }

        private void MCLACheckBox_CheckedChanged(object sender, EventArgs e)
        {
            useMCLA = ((CheckBox)sender).Checked;
        }

        private void CSPACheckBox_CheckedChanged(object sender, EventArgs e)
        {
            useCSPA = ((CheckBox)sender).Checked;
        }

        private void CASLACheckBox_CheckedChanged(object sender, EventArgs e)
        {
            useCASLA = ((CheckBox)sender).Checked;
        }

        private void VYSmooth_TextChanged(object sender, EventArgs e)
        {
            int n;
            if (int.TryParse(((TextBox)sender).Text, out n))
                VYSmoothNum = n;
        }

        private void button5_Click(object sender, EventArgs e)
        {
            m_IsAborting = true;
            this.toolStripStatusLabel1.Text = "Aborting";

            //cancel and remove all calculating threads
            if(CASLAWorker != null && !CSPAWorker.CancellationPending)
                CASLAWorker.CancelAsync();
            if(CSPAWorker != null && !CSPAWorker.CancellationPending)
                CSPAWorker.CancelAsync();
            if(MCLAWorker != null && !MCLAWorker.CancellationPending)
                MCLAWorker.CancelAsync();
            if(partitionWorker != null && !partitionWorker.CancellationPending)
                partitionWorker.CancelAsync();

            //cancel and remove all progress bar threads
            for (int i = 0; i < m_workers.Count; i++)
            {
                m_workers[i].CancelAsync();
                m_resetEvent.WaitOne();
                m_workers.RemoveAt(i);
            }

            //restore control on controls
            foreach (Control control in this.Controls)
            {
                if (control.Name.Equals("button5"))
                    control.Enabled = false;
                else
                    control.Enabled = true;
            }            
        }

    }
}
